/*************************************************************************
 *
 *  Copyright (C) 2013 Florian Dang <florian.coin@gmail.com>
 *
 *  This file is part of NatusVerse.
 *
 *  NatusVerse is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  NatusVerse is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with NatusVerse.  If not, see <http://www.gnu.org/licenses/>.
 *
 *************************************************************************/

#ifndef INC_RAYTRACER_OBJECTS_MATERIAL_H_
#define INC_RAYTRACER_OBJECTS_MATERIAL_H_

/*!
 * \file        material.h
 * \brief       Object material type
 * \author      Florian Dang
 * \date        2013
 */

#include "raytracer/objects/point.h"
#include "raytracer/objects/ray.h"
#include "raytracer/objects/light.h"
#include "graphics/color.h"

namespace raytracer
{
//! Material class
/*!
  Describe of what the object is made
*/
class Material
{
	public:
		typedef color::Color Color;
		typedef std::vector<Light> VecLight;

		enum MatType
		{
			kGouraud    = 0,
			kNoise      = 1,
			kMarble     = 2,
			kTurbulence = 3
		};

		Material() {}

		Material(MatType type0, Color colreflect0)
			: type_(type0), color_reflect_(colreflect0), coeff_reflect_(0.8f),
			  color_refract_(colreflect0), coeff_refract_(0.0f), specular_(1.0f),
			  rugosity_(100.0f) {}

		Material(MatType type0, Color colreflect0, float coeffreflect0, 
				 Color colrefract0, float coeffrefract0)
			: type_(type0), color_reflect_(colreflect0), coeff_reflect_(coeffreflect0),
			  color_refract_(colrefract0), coeff_refract_(coeffrefract0), specular_(1.0f),
			  rugosity_(100.0f) {}

		// same color for reflect and refract
		Material(MatType type0, Color colreflect0, float coeffreflect0, 
				 float coeffrefract0)
			: type_(type0), color_reflect_(colreflect0), coeff_reflect_(coeffreflect0),
			  color_refract_(colreflect0), coeff_refract_(coeffrefract0), specular_(1.0f),
			  rugosity_(100.0f) {}


		Material(MatType type0, Color colreflect0, float coeffreflect0, 
				 Color colrefract0, float coeffrefract0, float specular0, float rugosity0)
			: type_(type0), color_reflect_(colreflect0), coeff_reflect_(coeffreflect0),
			  color_refract_(colrefract0), coeff_refract_(coeffrefract0), 
			  specular_(specular0), rugosity_(rugosity0) {}

		~Material() {}

		void Print() const;

		inline MatType type() const { return type_; }
		inline Color   color_reflect() const { return color_reflect_; }
		inline float   coeff_reflect() const { return coeff_reflect_; }	
		inline Color   color_refract() const { return color_refract_; }
		inline float   coeff_refract() const { return coeff_refract_; }
		inline float   specular() const { return specular_; }
		inline float   rugosity() const { return rugosity_; }

		//! Bidirectional reflectance distribution function
		void  BrdfReflect(const Light& luminance, const float& coeff_brdf, Color& pixel_color);
		// ambient
		float BrdfLambert(const Ray& ray_light , const Vector& vec_normal, const float& coeff_recurs_reflect) const;
		// specular
		float BrdfPhong(const Ray& ray_light, const Vector& vec_normal, const float& coeff_recurs_reflect, const Ray& ray_view) const;
		float BrdfBlinnPhong(const Ray& ray_light, const Vector& vec_normal, const float& coeff_recurs_reflect, const Ray& ray_view) const;

		float Refraction(Ray ray_light, Vector vec_normal, float& coeff_recurs_refraction) const;
	private:
		MatType type_;
		Color   color_reflect_;
		float	coeff_reflect_;
		Color   color_refract_;
		float   coeff_refract_; // see indice IOR http://digital-lighting.150m.com/ch09lev1sec3.html
		float   specular_;   /*!< specular 0.0 and 1.0 */
		float   rugosity_;  /*!< Rugosity 0.0 and 1000.0 */

	// from KF Ray
	// * son type (normal ou avec texture procédurale en marbre, bois, turbulence...), <br>
	// * sa couleur en format RVB (chaque flottant est compris entre 0 et 255.0), <br>
	// * son coefficient de réflexion (compris entre 0.0 et 1.0 exclu), <br>
	// * son coefficient de réflexion spéculaire (compris entre 0.0 et 2.0), <br>
	// * son coefficient de rugosité (compris entre 0.0 et 1000.0), <br>
	// * son coefficient de bruit de Perlin (compris entre 0.0 et 2.0 : 1.0 par défaut), <br>
	// * son coefficient de bump mapping (compris entre 0.0 et 5.0 : 0.0 par défaut), <br>
	// * sa densité (compris entre 1.0 et 2.0 : 1.0 par défaut), <br>
	// * son coefficient réfraction (compris entre 0.0 et 1.0 : 0.0 par défaut).
};
}

#endif  // INC_RAYTRACER_OBJECTS_MATERIAL_H_
